package com.boco.fc.auto.deploy;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Map;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.SFTPv3Client;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import org.apache.log4j.Logger;

/**
 * 远程操作linux服务器，包括连接，删除文件或者目录，创建文件或目录，修改文件等
 * 
 * @author Administrator
 * 
 */
public class SSH2Util {
	public Logger log = Logger.getLogger(this.getClass());

	// 远端服务器IP地址
	private String serverIp;
	
	// 远端服务器端口
	private String serverPort;

	// 远端服务器登录用户名
	private String userName;

	// 远端服务器登录密码
	private String password;

	// 连接对象
	private Connection connection;

	// 连接状态
	private boolean isConnAndAuth = false;

	/**
	 * 默认构造函数，初始化服务IP地址，用户名，密码 基准目录等实例变量
	 */
	public SSH2Util() {
	}

	/**
	 * 根据传入的参数初始化服务IP地址，用户名，密码基准目录等实例变量
	 * 
	 * @param serverIp
	 * @param userName
	 * @param password
	 */
	public SSH2Util(String serverIp,String serverPort, String userName, String password) {
		this.serverIp = serverIp;
		this.serverPort = serverPort;
		this.userName = userName;
		this.password = password;
	}
	
	/**
	 * 根据传入的参数初始化服务IP地址，用户名，密码基准目录等实例变量
	 * 
	 * @param serverIp
	 * @param userName
	 * @param password
	 */
	public SSH2Util(Map<String, Object> server) {
		this.serverIp = (String)server.get("host");
		this.serverPort = (String)server.get("port");
		this.userName = (String)server.get("userName");
		this.password = (String)server.get("password");
	}

	/**
	 * 连接和认证远程Linux主机
	 * 
	 * @return boolean
	 * @throws Exception 
	 */
	public boolean connectAndAuth() throws Exception {
		if (null != serverIp) {
			if (!isConnAndAuth) {
				log.info("开始连接:" + serverIp);
				//connection = new Connection(serverIp);默认22端口
				connection = new Connection(serverIp,Integer.parseInt(serverPort));
				connection.connect();
				isConnAndAuth = connection.authenticateWithPassword(userName, password);
				Thread.sleep(100);
				if (isConnAndAuth) {
					log.info("连接成功:" + serverIp);
				} else {
					log.error("连接失败:" + serverIp + ",请检查IP，用户名或者密码是否正确!");
				}
			}
		}
		return this.isConnAndAuth;
	}

	/**
	 * 上传本地文件到远程服务器端，即将本地的文件localFile上传到远程Linux服务器中的remoteTargetDirectory目录下
	 * 
	 * @param localFile
	 * @param remoteTargetDirectory
	 */
	public void uploadFile(String localFile, String remoteTargetDirectory) throws Exception {
		log.info("本地文件：" + localFile);
		if (connectAndAuth()) {
			log.info("上传到远程：" + remoteTargetDirectory);
			SCPClient scpClient = connection.createSCPClient();
			scpClient.put(localFile, remoteTargetDirectory, "0644");
			Thread.sleep(100);
			log.info("成功==================================================");
		}
	}

	/**
	 * 从远程服务器端下载文件到本地指定的目录中
	 * 
	 * @param remoteFile
	 * @param localTargetDirectory
	 */
	public void downloadFile(String remoteFile, String localTargetDirectory) throws Exception {
		log.debug("远程文件：" + remoteFile);
		log.info("备份到" + localTargetDirectory);
		if (connectAndAuth()) {
			// 创建本地备份文件夹
			File file = new File(localTargetDirectory);
			if (!file.exists()) {
				file.mkdirs();
			}
			SCPClient scpClient = connection.createSCPClient();
			scpClient.get(remoteFile, localTargetDirectory);
			Thread.sleep(100);
			log.info("成功==================================================");
		}
	}

	/**
	 * 在远端linux上创建文件夹
	 * 
	 * @param dirName 文件夹名称
	 * @param posixPermissions 目录或者文件夹的权限
	 */
	public void mkDir(String dirName, int posixPermissions) throws Exception {
		log.info("远程目录创建：" + dirName);
		if (connectAndAuth()) {
			SFTPv3Client sftpClient = new SFTPv3Client(connection);
			sftpClient.mkdir(dirName, posixPermissions);
			Thread.sleep(100);
			log.info("成功==================================================");
		}
	}

	/**
	 * 删除远端Linux服务器上的文件
	 * 
	 * @param filePath
	 */
	public void rmFile(String filePath) throws Exception {
		log.info("删除文件：" + filePath);
		if (connectAndAuth()) {
			SFTPv3Client sftpClient = new SFTPv3Client(connection);
			sftpClient.rm(filePath);
			Thread.sleep(100);
			log.info("成功========================================");
		}
	}

	/**
	 * 删除远端Linux服务器上的一个空文件夹
	 * 
	 * @param dirName
	 */
	public void rmEmptyDir(String dirName) throws Exception {
		if (connectAndAuth()) {
			SFTPv3Client sftpClient = new SFTPv3Client(connection);
			sftpClient.rmdir(dirName);
		}
	}

	/**
	 * 在远程Linux服务器端移动文件或者文件夹到新的位置
	 * 
	 * @param oldPath
	 * @param newPath
	 */
	public void moveFileOrDir(String oldPath, String newPath) throws Exception {
		if (connectAndAuth()) {
			SFTPv3Client sftpClient = new SFTPv3Client(connection);
			sftpClient.mv(oldPath, newPath);
		}
	}

	/**
	 * 在远程Linux服务器上执行命令
	 * 命令执行状态为0，标识成功；其他为失败
	 * @param cmd
	 * @param isQuery
	 */
	public String execCommand(String cmd, boolean isQuery) throws Exception {
		log.info("执行命令: " + cmd);
		StringBuffer sb = new StringBuffer();
		if (connectAndAuth()) {
			Session session = null;
			if (isQuery) {
				// 获得推出状态
				log.info("执行结果: ");
				session = connection.openSession();
				session.execCommand(cmd);
				InputStream stdout = new StreamGobbler(session.getStdout());
				BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
				String content = null;
				while ((content = br.readLine()) != null) {
					sb.append(content);
					log.info(content);
				}
				Thread.sleep(100);
				Integer status = session.getExitStatus();
				log.debug("ExitCode: " + status);
				if (status != null && status.equals(0)) {
					log.info("执行成功");
				} else {
					log.error("执行失败");
				}
				session.close();
			} else {
				session = connection.openSession();
				session.execCommand(cmd);
				log.debug("ExitCode: " + session.getExitStatus());
				session.close();
			}
		}
		return sb.toString();
	}

	/**
	 * 在远程Linux服务器上执行ls 命令,以判断路径是否存在
	 * 命令执行状态为0，标识成功；其他为失败
	 * @param cmd
	 */
	public boolean exists(String path) throws Exception {
		boolean flag = false;
		StringBuffer sb = new StringBuffer();
		if (connectAndAuth()) {
			Session session = null;
			session = connection.openSession();
			session.execCommand("ls -l \"" + path + "\"");
			InputStream stdout = new StreamGobbler(session.getStdout());
			BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
			String content = null;
			while ((content = br.readLine()) != null) {
				sb.append(content);
			}
			Thread.sleep(100);
			// 获得推出状态
			log.debug("执行命令: " + "ls -l \"" + path + "\"");
			log.debug("执行结果: " + sb.toString());
			Integer status = session.getExitStatus();
			log.debug("ExitCode: " + status);
			if (status != null && status.equals(0)) {
				flag = true;
				log.info("远程路径存在：" + path);
			} else {
				flag = false;
				log.warn("远程路径不存在：" + path);
			}
			session.close();
		}
		return flag;
	}

	/**
	 * 在远程Linux服务器上执行mkdir 命令创建目录
	 * 
	 * @param cmd
	 */
	public boolean mkdirCmd(String path) throws Exception {
		boolean code = false;
		StringBuffer sb = new StringBuffer();
		if (connectAndAuth()) {
			Session session = null;
			session = connection.openSession();
			session.execCommand("mkdir -p \"" + path + "\"");
			InputStream stdout = new StreamGobbler(session.getStdout());
			BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
			String content = null;
			while ((content = br.readLine()) != null) {
				sb.append(content);
			}
			Thread.sleep(100);
			log.debug("执行命令: " + "mkdir -p \"" + path + "\"");
			Integer status = session.getExitStatus();
			log.debug("ExitCode: " + status);
			if (status != null && status.equals(0)) {
				log.info("远程目录创建成功:" + path);
			} else {
				log.error("远程目录创建失败:" + path);
			}
			session.close();
		}
		return code;
	}

	/**
	 * 关闭连接
	 * 
	 */
	public void closeConnection() {
		if (null != connection) {
			log.info("关闭连接:" + connection.getHostname());
			connection.close();
		}
	}

}
